/**
  * @File    :   sht3x.c
  * @Time    :   2020/04/02 13:14:48
  * @Author  :   huenrong
  */

#include "sht3x.h"
#include "../i2c/i2c.h"

/**
  * @name   sht3x_crc8
  * @brief  sht3x crc校验
  * @param  src_data: 源数据
  * @param  src_data_len: 源数据长度
  * @retval 成功: 返回0
            失败: 返回-1
  */
static uint16_t sht3x_crc8(const uint8_t *src_data, uint8_t src_data_len)
{
    uint8_t i = 0;
    uint8_t crc = 0xFF;

    for (; src_data_len > 0; src_data_len--)
    {
        crc ^= (*src_data++);
        for (i = 0; i < 8; i++)
        {
            if (crc & 0x80)
            {
                crc = (crc << 1) ^ 0x31;
            }
            else
            {
                crc <<= 1;
            }
        }
        crc &= 0xFF;
    }

    return (crc);
}

/**
  * @name   sht3x_read_temp_hum
  * @brief  sht3x读取温湿度数据
  * @param  read_temp: 读取到的温度值(单位: ℃)
  * @param  read_hum: 读取到的湿度值(单位: %RH)
  * @param  fd: 设备文件描述符
  * @retval 成功: 返回0
            失败: 返回-1
  */
int sht3x_read_temp_hum(float *read_temp, float *read_hum, const int fd)
{
    int ret = -1;
    uint8_t sht3x_send_buf[3] = {0};
    uint8_t sht3x_read_data[7] = {0};

    // 设置从器件地址
    // 不带寄存器地址的从设备操作前需要先设置从器件地址
    if (ioctl(fd, I2C_SLAVE_FORCE, SHT3X_I2C_ADDR) < 0)
    {
        perror("sht3x set slave addr fail");

        return -1;
    }

    // sht3x软件复位
    memset(sht3x_send_buf, 0, sizeof(sht3x_send_buf));
    sht3x_send_buf[0] = 0x30;
    sht3x_send_buf[1] = 0xA2;
    ret = i2c_write_data(fd, sht3x_send_buf, 2);
    if (0 != ret)
    {
        printf("sht3x software reset fail\n");

        return -1;
    }
    usleep(20 * 1000);

    // sht3x配置工作模式(启用时钟延展的高重复性测量)
    memset(sht3x_send_buf, 0, sizeof(sht3x_send_buf));
    sht3x_send_buf[0] = 0x2C;
    sht3x_send_buf[1] = 0x06;
    ret = i2c_write_data(fd, sht3x_send_buf, 2);
    if (0 != ret)
    {
        printf("sht3x set mode fail\n");

        return -1;
    }
    usleep(20 * 1000);

    // sht3x读取温湿度数据
    memset(sht3x_read_data, 0, sizeof(sht3x_read_data));
    ret = i2c_read_data(fd, 6, sht3x_read_data);
    if (0 != ret)
    {
        printf("sht3x read data fail\n");

        return -1;
    }

    // 计算温湿度数据的crc
    uint8_t temp_crc = sht3x_crc8(&sht3x_read_data[0], 2);
    uint8_t hum_crc = sht3x_crc8(&sht3x_read_data[3], 2);
    // 校验通过
    if ((temp_crc == sht3x_read_data[2]) && (hum_crc == sht3x_read_data[5]))
    {
        uint16_t temp = (sht3x_read_data[0] << 8) + sht3x_read_data[1];
        uint16_t hum = (sht3x_read_data[3] << 8) + sht3x_read_data[4];

        *read_temp = (((temp * 175) / 65535.0) - 45); // 单位℃
        *read_hum = ((hum * 100) / 65535.0);          // 单位%RH

        return 0;
    }

    return -1;
}
